import java.util.concurrent.Semaphore;

public class ExampleApl implements Runnable {
	private Semaphore first;
	private Semaphore second;

	public static void main(String[] args) throws Exception {
		Semaphore s1 = new Semaphore(1);
		Semaphore s2 = new Semaphore(1);

		Thread t = new Thread(new ExampleApl(s1, s2));
		// now reverse them ... here comes trouble!
		Thread t2 = new Thread(new ExampleApl(s1, s2));
		Thread t3 = new Thread(new ExampleApl(s2, s1));

		t.start();
		t2.start();
		t3.start();

		t.join();
		t2.join();
		t3.join();
		System.out.println("We got lucky!");
	}

	public ExampleApl(Semaphore s1, Semaphore s2) {
		first = s1;
		second = s2;
	}

	public void run() {
		try {
			Thread t = Thread.currentThread();

			first.acquireUninterruptibly();
			System.out.println(t + " acquired " + first);
			

			//Thread.sleep(200); // demonstrate deadlock

			second.acquire();
			System.out.println(t + " acquired " + second);
			first.release();
			second.release();
			System.out.println(t + " released " + second);

			first.release();
			System.out.println(t + " released " + first);
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		}
	}
}
